package com.bzkj.basicinfo.service.stock.impl;

import com.bzkj.basicinfo.domain.stock.WmsStockEntity;
import com.bzkj.basicinfo.domain.stock.WmsStockLockEntity;
import com.bzkj.basicinfo.domain.stock.WmsStockLogEntity;
import com.bzkj.basicinfo.mapper.stock.WmsStockLockMapper;
import com.bzkj.basicinfo.mapper.stock.WmsStockLogMapper;
import com.bzkj.basicinfo.mapper.stock.WmsStockMapper;
import com.bzkj.basicinfo.service.stock.WmsStockService;
import com.bzkj.common.core.domain.AjaxResult;
import com.bzkj.common.utils.DateUtils;
import com.bzkj.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

import static com.bzkj.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * WMS库存管理服务实现类
 *
 * @author WMS
 * @date 2025-10-23
 */
@Service
public class WmsStockServiceImpl implements WmsStockService {

    @Autowired
    private WmsStockLockMapper stockLockMapper;

    @Autowired
    private WmsStockLogMapper stockLogMapper;

    // TODO: 需要注入实际的库存表Mapper，这里暂时用注释模拟
     @Autowired
     private WmsStockMapper stockMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult increaseStock(String productId, String productCode, String productName,
                                  String batchCode, String locationCode, BigDecimal quantity,
                                  String bizType, String bizNo, String operator) {
        try {
            // 参数校验
            if (StringUtils.isEmpty(productId)) {
                return AjaxResult.error("商品ID不能为空");
            }
            if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
                return AjaxResult.error("增加数量必须大于0");
            }

            // TODO: 实际库存增加逻辑
//             这里需要根据实际的库存表结构来实现
//             1. 查询现有库存记录
             WmsStockEntity existStock = stockMapper.selectStock(productId, batchCode, locationCode);
//             2. 如果存在，更新数量；如果不存在，创建新记录
             if (existStock != null) {
                 BigDecimal newQuantity = existStock.getQuantity().add(quantity);
                 existStock.setQuantity(newQuantity);
                 existStock.setUpdateBy(operator);
                 existStock.setUpdateTime(new Date());
                 stockMapper.updateStock(existStock);
             } else {
                 WmsStockEntity newStock = new WmsStockEntity();
                 newStock.setProductId(productId);
                 newStock.setProductCode(productCode);
                 newStock.setProductName(productName);
                 newStock.setBatchCode(batchCode);
                 newStock.setLocationCode(locationCode);
                 newStock.setQuantity(quantity);
                 newStock.setAvailableQuantity(quantity);
                 newStock.setLockedQuantity(BigDecimal.ZERO);
                 newStock.setCreateBy(operator);
                 newStock.setCreateTime(new Date());
                 stockMapper.insertStock(newStock);
             }

            // 3. 记录库存变更日志
            createStockLog(productId, productCode, productName, batchCode, locationCode,
                         quantity, "ADD", bizType, bizNo, operator);

            return AjaxResult.success("库存增加成功");
        } catch (Exception e) {
            throw new RuntimeException("库存增加异常：" + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult decreaseStock(String productId, String productCode, String productName,
                                  String batchCode, String locationCode, BigDecimal quantity,
                                  String bizType, String bizNo, String operator) {
        try {
            // 参数校验
            if (StringUtils.isEmpty(productId)) {
                return AjaxResult.error("商品ID不能为空");
            }
            if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
                return AjaxResult.error("减少数量必须大于0");
            }

            // 检查库存是否充足
            if (!checkStockSufficient(productId, batchCode, locationCode, quantity)) {
                return AjaxResult.error("库存不足，无法减少");
            }

            // TODO: 实际库存减少逻辑
            // WmsStockEntity existStock = stockMapper.selectStock(productId, batchCode, locationCode);
            // if (existStock == null) {
            //     return AjaxResult.error("库存记录不存在");
            // }
            //
            // BigDecimal newQuantity = existStock.getQuantity().subtract(quantity);
            // if (newQuantity.compareTo(BigDecimal.ZERO) < 0) {
            //     return AjaxResult.error("库存不足");
            // }
            //
            // existStock.setQuantity(newQuantity);
            // BigDecimal newAvailable = existStock.getAvailableQuantity().subtract(quantity);
            // existStock.setAvailableQuantity(newAvailable);
            // existStock.setUpdateBy(operator);
            // existStock.setUpdateTime(new Date());
            // stockMapper.updateStock(existStock);

            // 记录库存变更日志
            createStockLog(productId, productCode, productName, batchCode, locationCode,
                         quantity, "REDUCE", bizType, bizNo, operator);

            return AjaxResult.success("库存减少成功");
        } catch (Exception e) {
            throw new RuntimeException("库存减少异常：" + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult lockStock(String productId, String batchCode, String locationCode,
                              BigDecimal quantity, String lockType, String relatedOrderNo,
                              String relatedOrderType, String operator) {
        try {
            // 参数校验
            if (StringUtils.isEmpty(productId)) {
                return AjaxResult.error("商品ID不能为空");
            }
            if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
                return AjaxResult.error("锁定数量必须大于0");
            }

            // 检查可用库存是否充足
            BigDecimal availableStock = getAvailableStock(productId, batchCode, locationCode);
            if (availableStock.compareTo(quantity) < 0) {
                return AjaxResult.error("可用库存不足，无法锁定");
            }

            // 生成锁定编号
            String lockNo = generateLockNo(lockType);

            // 创建锁定记录
            WmsStockLockEntity lockEntity = new WmsStockLockEntity();
            lockEntity.setLockNo(lockNo);
            // lockEntity.setStockId(stockId); // TODO: 需要从库存表查询stockId
            lockEntity.setProductId(productId);
            lockEntity.setBatchCode(batchCode);
            lockEntity.setUnitCode(locationCode); // 这里映射为货位编码
            lockEntity.setLockedQuantity(quantity);
            lockEntity.setLockType(lockType);
            lockEntity.setRelatedOrderNo(relatedOrderNo);
            lockEntity.setRelatedOrderType(relatedOrderType);
            lockEntity.setLockStatus("locked");
            lockEntity.setLockTime(new Date());
            lockEntity.setOperator(operator);
            lockEntity.setCreateBy(operator);
            lockEntity.setCreateTime(new Date());

            int rows = stockLockMapper.insertStockLock(lockEntity);
            if (rows <= 0) {
                return AjaxResult.error("创建锁定记录失败");
            }

            // TODO: 更新库存表的锁定数量
            // WmsStockEntity stock = stockMapper.selectStock(productId, batchCode, locationCode);
            // stock.setLockedQuantity(stock.getLockedQuantity().add(quantity));
            // stock.setAvailableQuantity(stock.getAvailableQuantity().subtract(quantity));
            // stockMapper.updateStock(stock);

            return AjaxResult.success("库存锁定成功", lockNo);
        } catch (Exception e) {
            throw new RuntimeException("库存锁定异常：" + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult unlockStock(String lockNo, String operator) {
        try {
            // 查询锁定记录
            WmsStockLockEntity lockEntity = stockLockMapper.selectStockLockByLockNo(lockNo);
            if (lockEntity == null) {
                return AjaxResult.error("锁定记录不存在");
            }

            if (!"locked".equals(lockEntity.getLockStatus())) {
                return AjaxResult.error("库存已解锁，无需重复操作");
            }

            // 更新锁定记录状态
            lockEntity.setLockStatus("unlocked");
            lockEntity.setUnlockTime(new Date());
            lockEntity.setUpdateBy(operator);
            lockEntity.setUpdateTime(new Date());

            int rows = stockLockMapper.updateStockLock(lockEntity);
            if (rows <= 0) {
                return AjaxResult.error("解锁库存失败");
            }

            // TODO: 更新库存表的锁定数量
            // WmsStockEntity stock = stockMapper.selectStock(lockEntity.getProductId(),
            //     lockEntity.getBatchCode(), lockEntity.getUnitCode());
            // stock.setLockedQuantity(stock.getLockedQuantity().subtract(lockEntity.getLockedQuantity()));
            // stock.setAvailableQuantity(stock.getAvailableQuantity().add(lockEntity.getLockedQuantity()));
            // stockMapper.updateStock(stock);

            return AjaxResult.success("库存解锁成功");
        } catch (Exception e) {
            throw new RuntimeException("库存解锁异常：" + e.getMessage(), e);
        }
    }

    @Override
    public boolean checkStockSufficient(String productId, String batchCode, String locationCode, BigDecimal requiredQuantity) {
        // TODO: 实际检查库存逻辑
        // WmsStockEntity stock = stockMapper.selectStock(productId, batchCode, locationCode);
        // if (stock == null) {
        //     return false;
        // }
        // return stock.getAvailableQuantity().compareTo(requiredQuantity) >= 0;

        // 暂时返回true，实际应该查询库存表
        return true;
    }

    @Override
    public BigDecimal getAvailableStock(String productId, String batchCode, String locationCode) {
        // TODO: 实际查询可用库存逻辑
        // WmsStockEntity stock = stockMapper.selectStock(productId, batchCode, locationCode);
        // if (stock == null) {
        //     return BigDecimal.ZERO;
        // }
        // return stock.getAvailableQuantity();

        // 暂时返回1000，实际应该查询库存表
        return new BigDecimal("1000");
    }

    @Override
    public BigDecimal getAvailableStockByProductId(String productId) {
        if (StringUtils.isEmpty(productId)) {
            return BigDecimal.ZERO;
        }
        try {
            BigDecimal stock = stockMapper.selectAvailableStockByProductId(productId);
            return stock != null ? stock : BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("查询商品可用库存失败，商品ID：{}，错误：{}", productId, e.getMessage());
            return BigDecimal.ZERO;
        }
    }

    // ========== 私有辅助方法 ==========

    /**
     * 创建库存变更日志
     */
    private void createStockLog(String productId, String productCode, String productName,
                              String batchCode, String locationCode, BigDecimal quantity,
                              String operType, String bizType, String bizNo, String operator) {
        String logNo = generateLogNo();

        WmsStockLogEntity logEntity = new WmsStockLogEntity();
        logEntity.setLogNo(logNo);
        logEntity.setBizType(bizType);
        logEntity.setBizNo(bizNo);
        logEntity.setProductId(productId);
        logEntity.setProductCode(productCode);
        logEntity.setProductName(productName);
        logEntity.setBatchCode(batchCode);
        logEntity.setLocationCode(locationCode);
        logEntity.setQuantity(quantity);
        logEntity.setOperType(operType);
        logEntity.setOperator(operator);
        logEntity.setOperTime(new Date());
        logEntity.setCreateBy(operator);
        logEntity.setCreateTime(new Date());

        stockLogMapper.insertStockLog(logEntity);
    }

    /**
     * 生成锁定编号
     */
    private String generateLockNo(String lockType) {
        String prefix = "LOCK";
        switch (lockType) {
            case "allocate":
                prefix = "ALLOC";
                break;
            case "freeze":
                prefix = "FREEZE";
                break;
            case "quality":
                prefix = "QUAL";
                break;
        }
        return prefix + DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS);
    }

    /**
     * 生成日志编号
     */
    private String generateLogNo() {
        return "LOG" + DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS);
    }
}